package com.dexter.year2023.charpter3_array.level2.topic2_6字符串替换空格;

/**
 * 替换空格
 * 来源：剑指offer 5. P51
 * <p>
 * 使用场景：
 * 在网络编程中，如果URL参数中含有特殊字符，如空格、'#'等，则可能导致服务器端无法获得正确的参数值。
 * 我们需要将这些特殊符号转换成服务器可以识别的字符。
 * 转换的规则是在'%'后面跟上ASCII码的两位十六进制的表示。
 * 比如空格的ASCII码是32，即十六进制的0x20，因此空格被替换成"%20"。
 * 再比如'#'的ASCII码是35，即十六进制的0x23，它在URL中被替换为"%23"。
 *
 * @author Dexter
 */
public class ReplaceSpace {
    /**
     * 将一个字符串中的每个空格替换成"%20"
     *
     * @param args
     */
    public static void main(String[] args) {
        StringBuffer sb = new StringBuffer("We are happy.");
        // 法1：res拼接字符
        System.out.println(replaceSpace(sb));
        // 法2：快慢双指针，从后往前遍历
        System.out.println(replaceSpace2(sb));
    }

    /**
     * 法1：最简单，长度不可变，另外申请空间
     *
     * @param str
     * @return
     */
    public static String replaceSpace(StringBuffer str) {
        String res = "";
        // 逐个字符判断
        for (int i = 0; i < str.length(); i++) {
            char c = str.charAt(i);
            if (c == ' ') {
                res += "%20";
            } else {
                res += c;
            }
        }
        return res;
    }

    /**
     * 法2：快慢双指针
     * 如果从头到尾判断，需要多次往后移动；可以巧妙地从后往前判断：
     * 第一次遍历，计算加上空格*2的总长度
     * 第二次从后往前开始替换
     *
     * @param str
     * @return
     */
    public static String replaceSpace2(StringBuffer str) {
        if (str == null) {
            return null;
        }
        // 空格数量
        int numOfBlank = 0;
        int len = str.length();
        // 第一次遍历
        for (int i = 0; i < len; i++) {
            if (str.charAt(i) == ' ') {
                numOfBlank++;
            }
        }
        // 标记长度
        str.setLength(len + numOfBlank * 2);
        // fast遍历原str
        int fast = len - 1;
        // slow替换新str
        int slow = (len + numOfBlank * 2) - 1;
        while (fast >= 0 && slow > fast) {
            char c = str.charAt(fast);
            if (c == ' ') {
                str.setCharAt(slow--, '0');
                str.setCharAt(slow--, '2');
                str.setCharAt(slow--, '%');
            } else {
                str.setCharAt(slow--, c);

            }
            fast--;
        }
        return str.toString();
    }
}
